#ifndef NctiScriptSolve_H
#define NctiScriptSolve_H
#include "NctiModelFunctionResult.h"
#include "ncti_base.h"
#include "dcl_ncti_pubfun.h"
#include <vector>
#include <map>
#include "NctiPosition.h"
#include "NctiVector.h"
#include "NctiThreadTask.h"
namespace NCTI
{
	struct ScriptConfig
	{
		EnumModelDoc ModelDoc;
		std::string TempSavePath;
	};
	struct DLLPlugin
	{
		std::string DllPath;
		std::vector<std::string> LoadDLLs;
	};
	typedef NctiModelFunctionResult(*NctiFunctionPtr)(const std::vector<std::string>& i_CommandArgument);
	class DECL_NCTI_PUBFUN NctiScriptSolveManager
	{
	public:
		NctiScriptSolveManager();
		~NctiScriptSolveManager();
	private:
		Ncti_Boolean m_hasLoaded;
		std::map<std::string, std::pair<std::string, NctiFunctionPtr>> m_CommandMap;
		ScriptConfig m_ScriptConfig;
		std::string m_PyFunctionPath;
		std::string m_PythonPath;
		std::vector<std::string> m_ModelPaths;
		std::vector<DLLPlugin> m_LoadDLLs;

		//auto save
		std::string m_autoSaveFolder;
		Ncti_Integer m_autoSaveTime;
		Ncti_Boolean m_autoSaveValid;
	public:
		Ncti_Boolean GetCommand(const std::string& i_Script, std::string& o_Command);
		Ncti_Boolean GetCommandFun(const std::string& i_Script, NctiFunctionPtr& o_CommandFun);
		const ScriptConfig& GetScriptConfig() { return m_ScriptConfig; }
		std::vector<std::string> GetModelPaths() { return m_ModelPaths; }
		void SetModelPaths(const std::vector<std::string>& pathVec) { m_ModelPaths = pathVec; }
		std::vector<DLLPlugin> GetLoadDlls() { return m_LoadDLLs; }
		const char* GetPyFunctionPath() { return m_PyFunctionPath.c_str(); }
		const std::string& GetPythonPath() { return m_PythonPath; }
		//auto save 
		const char* GetAutoSaveFolder() { return m_autoSaveFolder.c_str(); }
		Ncti_Boolean GetAutoSaveValid() { return m_autoSaveValid; }
		Ncti_Integer GetAutoSaveTime() { return m_autoSaveTime; }
	public:
		static NctiScriptSolveManager* instance() { return m_instance; }
	private:
		static NctiScriptSolveManager* m_instance;
	public:
		Ncti_Boolean LoadConfig(const std::string& i_FileName);
		Ncti_Boolean ReadModelPath(const std::string& i_FileName);
		Ncti_Boolean ReadCommandNames(const std::string& i_FileName, std::vector<std::string>& o_CommandNames);
		Ncti_Boolean ReadSystemBase(const std::string& i_FileName, std::vector<std::string>& o_SystemBases);
	};
	class DECL_NCTI_PUBFUN NctiScriptSolve
	{
	public:
		NctiScriptSolve();
		~NctiScriptSolve();
	public:
		Ncti_Boolean LoadScript(const std::string& i_FileName);
		static Ncti_Boolean CommandScript(const std::string& i_script, std::vector<std::string>& o_ResultVec);
		const std::vector<std::vector<std::string>>& GetCommandVec() { return m_CommandVec; }
	private:
		std::vector<std::vector<std::string>> m_CommandVec;
	public:
		static Ncti_Boolean Argument(const std::string& i_argument, NctiPosition& o_pos);
		static Ncti_Boolean Argument(const std::string& i_argument, Ncti_Integer& o_num);
		static Ncti_Boolean Argument(const std::string& i_argument, Ncti_Double& o_dbl);
		static Ncti_Boolean Argument(const std::string& i_argument, NctiVector& o_vec);
		static Ncti_Boolean Argument(const std::string& i_argument, Ncti_UInteger& o_num);
	public:
		static Ncti_Boolean SolveEdgeName(const Ncti_Char* i_EdgeName, Ncti_UInteger& i_Index);
	};
	class DECL_NCTI_PUBFUN NctiScriptThreadTask : public NctiThreadTask
	{
	public:
		NctiScriptThreadTask();
		virtual ~NctiScriptThreadTask();
	public:
		NctiThreadAny run();
	private:
		//NctiScriptSolve* m_ScriptSolve;
		std::string m_FileName;
		std::string m_TypeName;
	private:
		void RunScriptSolve(const std::string& i_TypeName, const std::string& i_FileName);
	public:
		static void RunScriptSolve(const std::string& i_TypeName, const std::vector<std::string>& i_FileNameVec);
		static void RunPython(const std::string& i_TypeName, const std::string& i_FileName);
		static void RunPythonEx(const std::string& i_TypeName, const std::string& i_FileName);
	};
}
#endif // !NctiScriptSolve_H
